#include"com.h"
#include<signal.h>
#include<sys/wait.h>

void Usage(string proc)
{
  cout<<"Usage: "<<proc<<"port"<<endl;
}


void Server(int new_sock) //处理任务
{   
  while(1)
  {
    char buffer[1024] = {0};
    ssize_t s = read(new_sock,buffer,sizeof(buffer)-1);
    if(s>0)
    {
      buffer[s]='\0';
      cout<<"client:# "<<buffer<<endl;
      string echo = "get->: ";
      echo+=buffer;
      write(new_sock,echo.c_str(),echo.size());
    }
    else if(s==0)
    {
      cout<<"client quit....."<<endl;
      break;
    }
    else 
    {
      cerr<<"read fail"<<endl;
      break;
    }

  }
}

int main(int argc,char* argv[])
{
  if(argc!=2)
  {
    Usage(argv[0]);
    return 2;
  }
  //创建套接字
  int sock = socket(AF_INET,SOCK_STREAM,0);
  if(sock<0)
  {
    cerr<<"socket fail"<<errno<<endl;
    return 1;
  }
  //绑定
  struct sockaddr_in local;
  memset(&local,0,sizeof(local));
  local.sin_family=AF_INET; 
  local.sin_port=htons(atoi(argv[1]));
  local.sin_addr.s_addr=INADDR_ANY;
  if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0) 
  {
    cerr<<"bind error: "<<errno<<endl;
    return 3;
  }
  //监听
  if(listen(sock,5)<0)
  {
    cerr<<"listen fail"<<endl;
    return 4;
  }
 //  signal(SIGCHLD,SIG_IGN);
  while(true)
  {
    struct sockaddr_in peer;  
    memset(&peer,0,sizeof(peer));
    socklen_t len= sizeof(peer);
    int new_sock = accept(sock,(struct sockaddr*)&peer,&len);

    if(new_sock<0)
    {
      continue;
    }
    uint16_t cli_port = ntohs(peer.sin_port);
    string cli_ip = inet_ntoa(peer.sin_addr);
    
    cout<<"get a new link->"<<cli_ip<<" "<<cli_port<<endl;

    pid_t id=fork();
    if(id<0)
    {
      continue;
    }
    else if(id==0)
    {
      close(sock);
      if(fork()>0) exit(0);//退出的是子进程
      //向后走的进程，是孙子进程，后续退出会被操作系统领养
      Server(new_sock);
      close(new_sock);//服务完成，关闭描述符,不关闭，导致文件描述符泄露 
      exit(0);
    }

    else
    {
      close(new_sock); //这个文件描述符已经给子进程了
      waitpid(id,nullptr,0);
      //父进程忽略//1.signal(SIGCHLD,SIG_IGN);2.
    }

  }

  return 0;
}
